index.ts ➔ sort   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
// Type definitions for object types and non-sortable types
2
type ObjectType = Record<string | symbol, unknown>;
3
type SortedEntry = [string | symbol, unknown];
4
type NonSortableType = Date | RegExp | Function | Error | Map<unknown, unknown> | Set<unknown> | WeakMap<object, unknown> | WeakSet<object> | Promise<unknown>;
5
6
// Main sorting function that can handle various data types
7 1
export function sort<T>(data: T, ascending = true): T {
8 21
  return sortRecursively(data, ascending);
9
}
10
11
// Recursive function to sort nested structures
12
function sortRecursively<T>(data: T, ascending: boolean): T {
13 140
  if (!isObject(data) || Array.isArray(data) || isNonSortableObject(data)) {
14 108
    return Array.isArray(data) ? data.map(item => sortRecursively(item, ascending)) as T : data;
15
  }
16
17 32
  return sortObject(data as ObjectType, ascending) as T;
18
}
19
20
// Helper function to check if a value is an object
21
function isObject(data: unknown): data is ObjectType {
22 140
  return typeof data === 'object' && data !== null;
23
}
24
25
// Function to sort object properties
26
function sortObject(obj: ObjectType, ascending: boolean): ObjectType {
27 32
  const entries = [...Object.entries(obj), ...Object.getOwnPropertySymbols(obj).map(sym => [sym, obj[sym]] as SortedEntry)];
28
  
29 32
  const sortedEntries = entries.sort(([keyA], [keyB]) => {
30 72
    if (typeof keyA === 'symbol' && typeof keyB === 'symbol') return 0;
31 71
    if (typeof keyA === 'symbol') return 1;
32 68
    if (typeof keyB === 'symbol') return -1;
33 68
    return ascending ? (keyA as string).localeCompare(keyB as string) : (keyB as string).localeCompare(keyA as string);
34
  });
35
36 83
  return Object.fromEntries(sortedEntries.map(([key, value]) => [key, sortRecursively(value, ascending)]));
37
}
38
39
// Helper function to check if an object is of a non-sortable type
40
function isNonSortableObject(obj: unknown): obj is NonSortableType {
41 49
  const nonSortableTypes = [Date, RegExp, Function, Error, Map, Set, WeakMap, WeakSet, Promise];
42 351
  return nonSortableTypes.some(type => obj instanceof type) || Symbol.iterator in Object(obj);
43
}
44